package com.dove.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dove.common.IgnoreLogin;
import com.dove.common.Result;
import com.dove.mapper.FileEntityMapper;
import com.dove.entity.FileEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 文件上传相关接口
 */
@RestController
@RequestMapping("/files")
public class FileController {

    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Resource
    private FileEntityMapper fileMapper;

    //自定义注解权限放行
    @IgnoreLogin
    @GetMapping("/front/all")
    public Result frontAll(){
        return Result.success(fileMapper.selectList(null));
    }

    @DeleteMapping("{id}")
    public Result modify(@PathVariable Integer id) {
        FileEntity fileEntity = fileMapper.selectById(id);
        fileEntity.setIsDelete(true);
        int i = fileMapper.updateById(fileEntity);
        if (i>0) {
            return Result.success("修改成功");
        }
        return Result.error("修改失败");
    }

    @PostMapping("/update")
    public Result update(@RequestBody FileEntity fileEntity) {
        int i = fileMapper.updateById(fileEntity);
        if (i>0) {
            return Result.success("更新成功");
        }
        return Result.error("更新失败");
    }

    @PostMapping("/del/batch")
    public Result deleteBatch(@RequestBody List<Integer> ids) {
        //select * form sys_file where id in (id,id...)
        QueryWrapper<FileEntity> qw = new QueryWrapper<>();
        qw.in("id",ids);
        List<FileEntity> fileList = fileMapper.selectList(qw);
        for (FileEntity file : fileList) {
            file.setIsDelete(true);
            fileMapper.updateById(file);
        }
        if (fileList!=null) {
            return Result.success("批量操作成功");
        }
        return Result.error("批量操作失败");
    }

    @GetMapping("/page")
    public Result getPage2(@RequestParam("pageNum") Integer current, @RequestParam("pageSize") Integer size,
                           @RequestParam(defaultValue = "") String name) {
        //请求参数和形式参数同名，自动注入，或者直接模型类中的属性和请求参数相同，也会直接注入到模型类中
        IPage<FileEntity> page = new Page<>(current, size);
        QueryWrapper<FileEntity> qw = new QueryWrapper<>();
        qw.eq("is_delete",false);
        if (!"".equals(name)) {
            qw.like("name", name);
        }
        return Result.success(fileMapper.selectPage(page,qw));
    }

    /**
     * 文件上传
     *
     * @param file 前端上传文件
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize();

        //定义文件唯一标识码
        String uuid = IdUtil.fastSimpleUUID();
        String fileUUID = uuid + StrUtil.DOT + type;
        File uploadFile = new File(fileUploadPath + fileUUID);
        //判断配置文件目录是否存在，若不存在则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        String url;
        //上传文件到磁盘
        file.transferTo(uploadFile);
        //获取文件md5
        String md5= SecureUtil.md5(uploadFile);
        //从数据库查询是否存在相同记录
        FileEntity dbFile = getFileByMD5(md5);
        //从数据库查询是否存在相同的记录
        if (dbFile!=null) {
            url=dbFile.getUrl();
            //由于文件已存在，所以删除刚才上传的重复文件
            uploadFile.delete();
        } else {
            //数据库若不存在重复文件则不删除刚才上传的文件
            url = "http://localhost:9090/files/" + fileUUID;
        }

        //存储到数据库
        FileEntity saveFile = new FileEntity();
        saveFile.setName(originalFilename);
        saveFile.setType(type);
        saveFile.setSize(size / 1024);
        saveFile.setUrl(url);
        saveFile.setMd5(md5);
        fileMapper.insert(saveFile);
        return url;
    }

    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        //根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        //设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");
        //读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    private FileEntity getFileByMD5(String md5) {
        //获取md5
        QueryWrapper<FileEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<FileEntity> list = fileMapper.selectList(queryWrapper);
        return list.size()==0?null:list.get(0);
    }
}
